/******************************************************************************
*  Nano-RK, a real-time operating system for sensor networks.
*  Copyright (C) 2007, Real-Time and Multimedia Lab, Carnegie Mellon University
*  All rights reserved.
*
*  This is the Open Source Version of Nano-RK included as part of a Dual
*  Licensing Model. If you are unsure which license to use please refer to:
*  http://www.nanork.org/nano-RK/wiki/Licensing
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, version 2.0 of the License.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
*  Contributing Authors (specific to this file):
*  Zane Starr
*******************************************************************************/


#include <nrk.h>
#include <include.h>
#include <ulib.h>
#include <stdio.h>
#include <hal.h>
#include <nrk_error.h>
#include <nrk_timer.h>
#include <nrk_stack_check.h>
#include <nrk_stats.h>

// This needs to be loosened for kernel prints
#define SPIN_WAIT_TIME 850

inline void spin_wait_s(uint16_t wait_sec) {
  uint16_t s_cnt, ms_cnt;
    for (s_cnt = 0; s_cnt < wait_sec; s_cnt++) {
        for (ms_cnt = 0; ms_cnt < SPIN_WAIT_TIME; ms_cnt++) {
            //spinwait 1ms
            nrk_spin_wait_us(1000);
        }
    }
}

NRK_STK Stack1[NRK_APP_STACKSIZE];
nrk_task_type TaskOne;
void Task1(void);

NRK_STK Stack2[NRK_APP_STACKSIZE];
nrk_task_type CBS1;
void Task2 (void);

NRK_STK Stack3[NRK_APP_STACKSIZE];
nrk_task_type SystemStats;
void Task3 (void);

void nrk_create_taskset();

int
main ()
{
  nrk_setup_ports();
  nrk_setup_uart(UART_BAUDRATE_115K2);

  printf( "Starting up...\r\n" );

  nrk_init();
  nrk_led_clr(ORANGE_LED);
  nrk_led_clr(BLUE_LED);
  nrk_led_set(GREEN_LED);
  nrk_led_clr(RED_LED);
  nrk_time_set(0,0);
  nrk_create_taskset ();
  nrk_start();
  
  return 0;
}


void Task1()
{
uint16_t cnt;
int8_t v;

  while(1) {
	  printf("Task 1 is running");
    spin_wait_s(4); // Set the task to 4 seconds
	  nrk_wait_until_next_period();
  }
}

void Task2()
{
  uint8_t cnt;
  int8_t v;

  while(1) {
    printf("Task2 is running");
    spin_wait_s(4); // is spin locking really the problem?
    nrk_wait_until_next_period();
  }
}

void Task3() {
  while(1) {
    nrk_print_readyQ();
    nrk_wait_until_next_period();
  }
}

void nrk_create_taskset()
{
  //Task 1 is the Hard Realtime Task
  nrk_task_set_entry_function(&TaskOne, Task1);
  nrk_task_set_stk( &TaskOne, Stack1, NRK_APP_STACKSIZE);
  TaskOne.prio = 1;                     // Doesn't matter, we're doing CBS
  TaskOne.FirstActivation = TRUE;
  TaskOne.Type = BASIC_TASK;
  TaskOne.SchType = PREEMPTIVE;
  TaskOne.period.secs = 7;
  TaskOne.period.nano_secs = 0;
  TaskOne.cpu_reserve.secs = 4;
  TaskOne.cpu_reserve.nano_secs = 0;
  TaskOne.offset.secs = 0;
  TaskOne.offset.nano_secs= 0;
  nrk_activate_task (&TaskOne);

  //Task 2 is the Soft-Realtime CBS Server
  nrk_task_set_entry_function(&CBS1, Task2);
  nrk_task_set_stk(&CBS1, Stack2, NRK_APP_STACKSIZE);
  CBS1.prio = 1;                     // Doesn't matter, we're doing CBS
  CBS1.FirstActivation = TRUE;
  CBS1.Type = CBS_TASK;
  CBS1.SchType = PREEMPTIVE;
  CBS1.period.secs = 8;
  CBS1.period.nano_secs = 0;
  CBS1.cpu_reserve.secs = 3;
  CBS1.cpu_reserve.nano_secs = 0;
  CBS1.offset.secs = 0;
  CBS1.offset.nano_secs= 0;
  nrk_activate_task (&CBS1);

  //Task 3 is the hard Realtime print CBS Server
  nrk_task_set_entry_function(&SystemStats, Task3);
  nrk_task_set_stk(&SystemStats, Stack3, NRK_APP_STACKSIZE);
  SystemStats.prio = 1;                     // Doesn't matter, we're doing CBS
  SystemStats.FirstActivation = TRUE;
  SystemStats.Type = BASIC_TASK;
  SystemStats.SchType = PREEMPTIVE;
  SystemStats.period.secs = 1;
  SystemStats.period.nano_secs = 0;
  SystemStats.cpu_reserve.secs = 1;
  SystemStats.cpu_reserve.nano_secs = 0;
  SystemStats.offset.secs = 0;
  SystemStats.offset.nano_secs= 0;
  //nrk_activate_task (&SystemStats);
}



